package org.example.system.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import io.swagger.v3.oas.annotations.Parameter;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.example.system.common.result.PageResult;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.example.system.common.result.Result;
import org.example.system.common.util.ExcelUtils;
import org.example.system.model.dto.RegisterDTO;
import org.example.system.model.form.UserForm;
import org.example.system.model.query.UserPageQuery;
import org.example.system.model.vo.UserExportVO;
import org.example.system.model.vo.UserImportVO;
import org.example.system.model.vo.UserInfoVO;
import org.example.system.model.vo.UserPageVO;
import org.example.system.plugin.dupsubmit.annotation.PreventDuplicateSubmit;
import org.example.system.plugin.easyexcel.UserImportListener;
import org.example.system.service.SysUserService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 用户控制器
 * 处理用户相关的请求
 * 包括获取当前用户信息、用户分页列表、新增、修改、删除用户等
 *
 * @author LY
 */
@Tag(name = "02.用户接口")
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class SysUserController {

    private final SysUserService userService;

    // 权限常量
    private static final String PERM_USER_ADD = "sys:user:add";
    private static final String PERM_USER_EDIT = "sys:user:edit";
    private static final String PERM_PASSWORD_RESET = "sys:user:password_reset";
    private static final String PERM_USER_DEL = "sys:user:delete";

    /**
     * 获取当前登录用户信息
     *
     * @return 当前用户信息
     */
    @Operation(summary = "获取当前登录用户信息")
    @GetMapping("/me")
    public Result<UserInfoVO> getCurrentUserInfo() {
        UserInfoVO userInfoVO = userService.getCurrentUserInfo();
        return Result.success(userInfoVO);
    }

    /**
     * 用户分页列表
     *
     * @param queryParams 查询参数
     * @return 用户分页结果
     */
    @Operation(summary = "用户分页列表")
    @GetMapping("/page")
    public PageResult<UserPageVO> listPagedUsers(@ParameterObject UserPageQuery queryParams) {
        IPage<UserPageVO> result = userService.listPagedUsers(queryParams);
        return PageResult.success(result);
    }

    /**
     * 新增用户
     *
     * @param userForm 用户表单数据
     * @return 操作结果
     */
    @Operation(summary = "新增用户")
    @PostMapping
    @PreAuthorize("@ss.hasPerm('" + PERM_USER_ADD + "')")
    @PreventDuplicateSubmit
    public Result<Boolean> saveUser(@RequestBody @Valid UserForm userForm) {
        boolean result = userService.saveUser(userForm);
        return Result.judge(result);
    }

    /**
     * 获取用户表单数据
     *
     * @param userId 用户ID
     * @return 用户表单数据
     */
    @Operation(summary = "用户表单数据")
    @GetMapping("/{userId}/form")
    public Result<UserForm> getUserForm(@Parameter(description = "用户ID") @PathVariable Long userId) {
        UserForm formData = userService.getUserFormData(userId);
        return Result.success(formData);
    }

    /**
     * 修改用户
     *
     * @param userId 用户ID
     * @param userForm 用户表单数据
     * @return 操作结果
     */
    @Operation(summary = "修改用户")
    @PutMapping("/{userId}")
    @PreAuthorize("@ss.hasPerm('" + PERM_USER_EDIT + "')")
    public Result<Boolean> updateUser(@Parameter(description = "用户ID") @PathVariable Long userId, @RequestBody @Validated UserForm userForm) {
        boolean result = userService.updateUser(userId, userForm);
        return Result.judge(result);
    }

    /**
     * 修改用户密码
     *
     * @param userId 用户ID
     * @param password 新密码
     * @return 操作结果
     */
    @Operation(summary = "修改用户密码")
    @PatchMapping("/{userId}/password")
    @PreAuthorize("@ss.hasPerm('" + PERM_PASSWORD_RESET + "')")
    public Result<Boolean> updatePassword(@Parameter(description = "用户ID") @PathVariable Long userId, @RequestParam String password) {
        boolean result = userService.updatePassword(userId, password);
        return Result.judge(result);
    }

    /**
     * 删除用户
     *
     * @param ids 用户ID，多个以英文逗号(,)分割
     * @return 操作结果
     */
    @Operation(summary = "删除用户")
    @DeleteMapping("/{ids}")
    @PreAuthorize("@ss.hasPerm('" + PERM_USER_DEL + "')")
    public Result<Boolean> deleteUsers(@Parameter(description = "用户ID，多个以英文逗号(,)分割") @PathVariable String ids) {
        boolean result = userService.deleteUsers(ids);
        return Result.judge(result);
    }

    /**
     * 用户导入模板下载
     *
     * @param response HTTP响应
     * @throws IOException IO异常
     */
    @Operation(summary = "用户导入模板下载")
    @GetMapping("/template")
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        String fileName = "用户导入模板.xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));

        String fileClassPath = "excel-templates" + File.separator + fileName;
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileClassPath);

        ServletOutputStream outputStream = response.getOutputStream();
        try (ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).build()) {
            excelWriter.finish();
        }
    }

    /**
     * 导入用户
     *
     * @param deptId 部门ID
     * @param file 上传的文件
     * @return 导入结果
     * @throws IOException IO异常
     */
    @Operation(summary = "导入用户")
    @PostMapping("/_import")
    public Result<String> importUsers(@Parameter(description = "部门ID") Long deptId, MultipartFile file) throws IOException {
        UserImportListener listener = new UserImportListener(deptId);
        String msg = ExcelUtils.importExcel(file.getInputStream(), UserImportVO.class, listener);
        return Result.success(msg);
    }

    /**
     * 导出用户
     *
     * @param queryParams 查询参数
     * @param response HTTP响应
     * @throws IOException IO异常
     */
    @Operation(summary = "导出用户")
    @GetMapping("/_export")
    public void exportUsers(UserPageQuery queryParams, HttpServletResponse response) throws IOException {
        String fileName = "用户列表.xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));

        List<UserExportVO> exportUserList = userService.listExportUsers(queryParams);
        EasyExcel.write(response.getOutputStream(), UserExportVO.class).sheet("用户列表").doWrite(exportUserList);
    }

    /**
     * 注册用户
     *
     * @param registerData 注册数据
     */
    @Operation(summary = "注册用户")
    @PostMapping("/register")
    public Result<Boolean> registerUser(@RequestBody @Validated RegisterDTO registerData) {
        System.out.println(registerData);
        boolean result = userService.registerUser(registerData);
        return Result.judge(result);
    }
}